package com.syh.jn.scm.service.impl.upstream.sale;

import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.driver.entity.logistics.DriverLogisticsBill;
import com.syh.jn.scm.domain.driver.event.DriverLogisticsBillEvent;
import com.syh.jn.scm.domain.upstream.entity.finance.UpStatementAccountBill;
import com.syh.jn.scm.domain.upstream.entity.logistics.UpLogisticsBill;
import com.syh.jn.scm.domain.upstream.entity.sale.UpSaleOrder;
import com.syh.jn.scm.domain.upstream.event.UpLogisticsBillEvent;
import com.syh.jn.scm.domain.upstream.event.UpSaleOrderEvent;
import com.syh.jn.scm.domain.upstream.event.UpStatementAccountBillEvent;
import com.syh.jn.scm.domain.upstream.repository.logistics.UpLogisticsBillRepository;
import com.syh.jn.scm.domain.upstream.repository.sale.UpSaleOrderRepository;
import com.syh.jn.scm.dto.support.FilesDto;
import com.syh.jn.scm.dto.upstream.sale.SaleStatisticalAmountVo;
import com.syh.jn.scm.dto.upstream.sale.UpSaleOrderVo;
import com.syh.jn.scm.service.api.upstream.finance.enums.UpStatementAccountBillEnum;
import com.syh.jn.scm.service.api.upstream.logistics.enums.UpLogisticsBillEnum;
import com.syh.jn.scm.service.api.upstream.sale.UpSaleOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class UpSaleOrderServiceImpl extends AbstractServiceImpl<Object, Object, UpSaleOrderVo, UpSaleOrder, Long> implements UpSaleOrderService {
  @Autowired
  private UpSaleOrderRepository upSaleOrderRepository;
  @Autowired
  private UpLogisticsBillRepository upLogisticsBillRepository;

  @Override
  protected AggregateRepository<UpSaleOrder, Long> getAggregateRepository() {
    return upSaleOrderRepository;
  }

  /**
   * 确认订单
   *
   * @param id
   */
  @Override
  public void confirm(Long id) {
    UpSaleOrder entity = idIsNull(id);
    entity.confirm();
    upSaleOrderRepository.update(entity, false);
  }

  /**
   * 反确认订单
   *
   * @param id
   */
  @Override
  public void antiConfirm(Long id) {
    UpSaleOrder entity = idIsNull(id);
    entity.stayConfirm();
    upSaleOrderRepository.update(entity, false);
    this.publicEvent(UpSaleOrderEvent.buildUpSaleOrderCancelConfirm(new Object[]{entity}));
  }

  /**
   * 取消订单
   *
   * @param id
   */
  @Override
  public void cancel(Long id) {
    UpSaleOrder entity = idIsNull(id);
    entity.cancel();
    upSaleOrderRepository.update(entity, false);
    this.publicEvent(UpSaleOrderEvent.buildUpSaleOrderCancel(new Object[]{entity}));
  }

  /**
   * 上传单据图片
   *
   * @param dto
   */
  @Override
  public void upload(FilesDto dto) {
    UpSaleOrder order = idIsNull(dto.getId());
    order.upload(dto);
    upSaleOrderRepository.upload(order);
  }

  @Override
  public SaleStatisticalAmountVo statisticalAmount(Wrapper we) {
    return upSaleOrderRepository.statisticalAmount(we);
  }

  @Override
  public List<SaleStatisticalAmountVo> statisticalAmountByCustomer(Wrapper we) {
    return upSaleOrderRepository.statisticalAmountByCustomer(we);
  }

  @Override
  public List<SaleStatisticalAmountVo> statisticalAmountByGoods(Wrapper we) {
    return upSaleOrderRepository.statisticalAmountByGoods(we);
  }

  /**
   * 校验订单是否存在
   *
   * @param id
   * @return
   */
  private UpSaleOrder idIsNull(Long id) {
    ExtAssert.notNull(id, "id为空");
    UpSaleOrder entity = upSaleOrderRepository.getById(id);
    ExtAssert.notNull(entity, "订单不存在");
    return entity;
  }

  /**
   * 消费者：监听物流单创建（记录生成物流商品数量）
   * @param bill
   */
  @DomainEventHandle(UpLogisticsBillEvent.UP_LOGISTICS_BILL_CREATED)
  protected void handleUpLogisticsBillCreated(UpLogisticsBill bill) {
    if (UpLogisticsBillEnum.ORDER_TYPE_SALE.getStatus().equals(bill.getOrderType())) {
      UpSaleOrder order = upSaleOrderRepository.getById(bill.getOrderId());
      order.countGeneratedQuantity(bill,1);
      upSaleOrderRepository.updateOrderAndItems(order);
    }
  }

  /**
   * 消费者：监听物流单删除（记录生成物流商品数量）
   * @param bill
   */
  @DomainEventHandle(UpLogisticsBillEvent.UP_LOGISTICS_BILL_DELETED)
  protected void handleUpLogisticsBillDeleted(UpLogisticsBill bill) {
    if (UpLogisticsBillEnum.ORDER_TYPE_SALE.getStatus().equals(bill.getOrderType())) {
      UpSaleOrder order = upSaleOrderRepository.getById(bill.getOrderId());
      order.countGeneratedQuantity(bill,2);
      upSaleOrderRepository.updateOrderAndItems(order);
    }
  }

  /**
   * 消费者：监听物流单发货（修改发货数量）
   * @param bill
   */
  @DomainEventHandle(UpLogisticsBillEvent.UP_LOGISTICS_BILL_DELIVERY)
  protected void handleLogisticsBillDelivery(UpLogisticsBill bill) {
    if (UpLogisticsBillEnum.ORDER_TYPE_SALE.getStatus().equals(bill.getOrderType())) {
      UpSaleOrder order = upSaleOrderRepository.getById(bill.getOrderId());
      order.delivery(bill);
      upSaleOrderRepository.updateOrderAndItems(order);
    }
  }

  /**
   * 消费者：监听司机端物流单发货（修改发货数量）
   * @param bill
   */
  @DomainEventHandle(DriverLogisticsBillEvent.DRIVER_LOGISTICS_BILL_DELIVERY)
  protected void handleDriverLogisticsBillDelivery(DriverLogisticsBill bill) {
    this.handleLogisticsBillDelivery(upLogisticsBillRepository.getById(bill.getId()));
  }

  /**
   * 消费者：监听物流单取消事件（修改发货数量）
   * @param bill
   */
  @DomainEventHandle(UpLogisticsBillEvent.UP_LOGISTICS_BILL_CANCELLED)
  protected void handleLogisticsBillCancelled(UpLogisticsBill bill) {
    if (UpLogisticsBillEnum.ORDER_TYPE_SALE.getStatus().equals(bill.getOrderType())) {
      UpSaleOrder order = upSaleOrderRepository.getById(bill.getOrderId());
      order.cancelDelivery(bill);
      upSaleOrderRepository.updateOrderAndItems(order);
    }
  }

  /**
   * 消费者：监听对账单（生成对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(UpStatementAccountBillEvent.UP_STATEMENT_BILL_ACCOUNT_CREATED)
  protected void handleUpStatementBillAccountCreated(UpStatementAccountBill bill) {
    bill.getUpStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(UpStatementAccountBillEnum.SOURCE_SALE_ORD.getStatus())) {
        UpSaleOrder saleOrder = upSaleOrderRepository.getById(billItem.getSourceId());
        saleOrder.generating(bill.getId());
        upSaleOrderRepository.update(saleOrder, false);
      }
    });
  }

  /**
   * 消费者：监听对账单（修改对账单状态）
   *
   * @param bill
   */
  @DomainEventHandle(UpStatementAccountBillEvent.UP_STATEMENT_BILL_ACCOUNT_UPDATA)
  protected void handleUpStatementBillAccountUpdata(UpStatementAccountBill bill) {
    Wrapper wrapper = Wrapper.build();
    wrapper.append(Restrictions.eq("statementId", bill.getId()));
    List<UpSaleOrder> upSaleOrders = upSaleOrderRepository.getList(wrapper);
    upSaleOrders.forEach(upSaleOrder -> {
      upSaleOrder.cancelGenerating();
      upSaleOrderRepository.update(upSaleOrder, false);
    });
    bill.getUpStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(UpStatementAccountBillEnum.SOURCE_SALE_ORD.getStatus())) {
        UpSaleOrder saleOrder = upSaleOrderRepository.getById(billItem.getSourceId());
        saleOrder.generating(bill.getId());
        upSaleOrderRepository.update(saleOrder, false);
      }
    });
  }

  /**
   * 消费者：监听对账单（删除对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(UpStatementAccountBillEvent.UP_STATEMENT_BILL_ACCOUNT_DESTORY )
  protected void handleUpStatementBillAccountDestory(UpStatementAccountBill bill) {
    bill.getUpStatementAccountBillItems().forEach( billItem -> {
      if (billItem.getSourceType().equals(UpStatementAccountBillEnum.SOURCE_SALE_ORD.getStatus())) {
        UpSaleOrder saleOrder = upSaleOrderRepository.getById(billItem.getSourceId());
        saleOrder.cancelGenerating();
        upSaleOrderRepository.update(saleOrder, false);
      }
    });
  }
}
